[org 0x7c00]

; 设置屏幕为文本模式，并清除屏幕
mov ax, 3
int 0x10

; 初始化段寄存器
mov ax, 0
mov ds, ax
mov es, ax
mov ss, ax

; 初始化栈指针
mov sp, 0x7c00

; xchg bx, bx

mov edi, 0x1000 ; 读数据存放的地址
mov ecx, 2      ; 起始扇区地址
mov bl, 4       ; 读扇区数量
call read_disk

cmp word [0x1000], 0xaa55
jnz error
jmp 0x1002

print:
    mov ah, 0x0e
.next:
    mov al, [si]
    cmp al, 0
    jz .done
    int 0x10
    inc si
    jmp .next
.done:
    ret

; 输入和输出只能用dx和ax寄存器
read_disk:
    mov dx, 0x1F2
    mov al, bl
    out dx, al  ; 读扇区数量

    inc dx  ; 0x1F3
    mov al, cl
    out dx, al  ; 起始扇区 0~7位

    inc dx  ; 0x1F4
    shr ecx, 8
    mov al, cl
    out dx, al  ; 起始扇区 8~15位
    
    inc dx  ; 0x1F5
    shr ecx, 8
    mov al, cl
    out dx, al  ; 起始扇区 16~23位
    
    inc dx  ; 0x1F6
    shr ecx, 8
    and cl, 0b1111
    mov al, 0b11100000
    or al, cl
    out dx, al  ; LBA, 主盘, 起始扇区 27~24位
    
    inc dx  ; 0x1F7
    mov al, 0x20    ; 读硬盘
    out dx, al
    
    xor ecx, ecx; 清空ecx
    mov cl, bl  ; 得到读扇区数量

.read:
    call .waits
    push cx
    call .reads
    pop cx
    loop .read
    ret

.reads:
    mov dx, 0x1F0
    mov cx, 256
.readw:
    in ax, dx
    jmp $+2
    jmp $+2
    jmp $+2
    jmp $+2
    jmp $+2 ; 延迟一会儿
    mov [edi], ax
    add edi, 2
    loop .readw
    ret

.waits:
    mov dx, 0x1F7
.check:
    in al, dx
    jmp $+2
    jmp $+2
    jmp $+2
    jmp $+2
    jmp $+2 ; 延迟一会儿
    and al, 0b00001000
    cmp al, 0b00001000
    jnz .check
    ret

error:
    mov si, message
    call print
    hlt ; Shut down the CPU
    jmp $

message:
    db "Booting Error!!!", 13, 10, 0;

; 填充 0
times 510 - ($ - $$)    db 0

; dw 0xaa55
db 0x55, 0xaa
